function lst = sllist(varargin)
%SLLIST Constructs a dynamic list object
%
% [ Syntax ]
%   - lst = sllist()
%   - lst = sllist(srclst)
%   - lst = sllist(capacity)
%   - lst = sllist(src)
%   - lst = sllist(capacity, src)
%   
% [ Arguments ]
%   - capacity:     The initially reserved capacity of the list
%   - srclst:       The source list
%   - src:          The source cell array or object array
%   - lst:          The constructed list object
%
% [ Description ]
%   - lst = sllist() constructs an empty list, with initial capacity 0.
%
%   - lst = sllist(srclist) constructs a shallow copy of the input 
%     list object. (copy constructor)
%
%   - lst = sllist(capacity) constructs an empty list with specified
%     capacity. 
%
%   - lst = sllist(src) constructs a list from the source cell array or
%     object array, whose initial capacity is set to the number of
%     source elements.
%
%   - lst = sllist(capacity, src) constructs a list initially containing
%     the elements in src, with specified capacity.
%
% [ Remarks ]
%   - The sllist class is to implement a dynamically-growing list data
%     structure. It supports the following functionalities
%
%       - cell-array-like subscript-based access
%       - cell-array-like subscript-based assignment
%       - cell: conversion to a cell array
%       - capacity: get the capacity of the list
%       - numel: get the number of elements in the list
%       - size:  return the size as it is an n x 1 array.
%       - length: get the number of elements in the list.
%       - vertcat: join multiple lists into one
%       - add: add one or multiple elements to the list
%       - append: append a list of multiple elements to the list
%       - remove_at: remove an element or multiple elements from the list
%       - select: select a sub list of elements based on predicate
%       - remove_if: remove elements based on predicate
%       - apply: apply a function to each element of the list
%       - grow: grow a list to at least the specified capacity
%       - reserve: reserve the capacity of a list to specified value
%
%   - This class serves as bases to implement other collections.
%
% [ History ]
%   - Created by Dahua Lin, on Jan 5, 2008
%

%% parse and verify input

error(nargchk(0, 2, nargin));

if nargin == 0  % empty list    
    C = {};
    ne = 0;
    
elseif nargin == 1    
    arg1 = varargin{1};
    
    if iscell(arg1)   % cell array
        if ndims(arg1) == 2 && size(arg1,2) == 1
            C = arg1;
        else
            C = arg1(:);
        end        
        ne = numel(C);
    
    elseif isa(arg1, 'sllist')  % copy construction
        lst = arg1;
        return;
        
    elseif isnumeric(arg1) && isscalar(arg1)  % initial capacity
        C = cell(arg1, 1);
        ne = 0;            
        
    elseif isobject(arg1)   % object array
        ne = numel(arg1);
        C = cell(ne, 1);
        for i = 1 : ne
            C{i} = arg1(i);
        end
        
    else
        error('sltoolbox:sllist:sllist:invalidarg', ...
            'Invalid argument for sllist construction.');
    end
    
else  % with both source and initial capacity
    
    capa = varargin{1};
    src = varargin{2};
    
    assert(isnumeric(capa) && isscalar(capa), ...
        'sltoolbox:sllist:sllist:invalidarg', ...
        'Invalid argument for sllist construction.');
    
    assert(iscell(src) || isobject(src), ...
        'sltoolbox:sllist:sllist:invalidarg', ...
        'Invalid argument for sllist construction.');
    
    ne = numel(src);
    capa = max(capa, ne);
    
    if capa == ne && iscell(src)
        if ndims(src) == 2 && size(src, 2) == 1
            C = src;
        else
            C = src(:);
        end
        
    else
        C = cell(capa, 1);
        
        if iscell(src)
            C(1:ne) = src(:);
            
        else
            for i = 1 : ne
                C{i} = src(i);
            end
        end
    end
    
end
    
% make object

lst = class(struct('items', {C}, 'n', ne), 'sllist');

            
        
    
    